package com.abou.mvc.format;

import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.PageContext;
import org.springframework.web.servlet.support.JspAwareRequestContext;
import org.springframework.web.servlet.support.RequestContext;
import org.springframework.web.servlet.tags.RequestContextAwareTag;
import com.abou.mvc.controller.ControllerUtils;
import com.abou.mvc.format.impl.CommonsMultipartFileFormatter;
import com.abou.mvc.format.impl.EnumFormatter;
import com.abou.mvc.format.impl.StringFormatter;

/**
 * The class providing formatting for use in JSP pages.
 * 
 * @author khalid
 */
public final class Formatter {
  
  /**
   * The list of the available formatters
   */
  private static final List<ITypeFormatter> FORMATTERS =
      Arrays.asList((ITypeFormatter) new EnumFormatter(),
          new StringFormatter(), new CommonsMultipartFileFormatter());
  
  /**
   * The private constructor to prevent the class from being instantiated
   */
  private Formatter() {

    super();
  }
  
  /**
   * Formats the passed value to a displayed string.
   * 
   * @param pageContext The page context
   * @param value The object to format
   * @return The displayable string
   */
  public static String format(PageContext pageContext, Object value) {

    return format(pageContext, value, false);
  }
  
  /**
   * Formats the passed value to a displayed string.
   * 
   * @param pageContext The page context
   * @param value The object to format
   * @param textOnly Whether the formatter string should be only a simple text
   *          (no HTML or image).
   * @return The displayable string
   */
  public static String format(PageContext pageContext, Object value,
      boolean textOnly) {

    // getting the request context
    RequestContext requestContext =
        (RequestContext) pageContext.findAttribute(RequestContextAwareTag.REQUEST_CONTEXT_PAGE_ATTRIBUTE);
    
    if (requestContext == null) {
      
      requestContext = new JspAwareRequestContext(pageContext);
    }
    
    return format(requestContext,
        (HttpServletRequest) pageContext.getRequest(), value, true, textOnly);
  }
  
  /**
   * Formats the passed value to a displayed string.
   * 
   * @param requestContext The request context
   * @param request The servlet request
   * @param value The object to format
   * @param formatEmptyValues Whether the empty or null values should be
   *          formatted according to a label set in the message resources.
   * @param textOnly Whether the formatter string should be only a simple text
   *          (no HTML or image).
   * @return The displayable string
   */
  public static String format(RequestContext requestContext,
      HttpServletRequest request, Object value, boolean formatEmptyValues,
      boolean textOnly) {

    // the text to return
    String text = null;
    
    if (requestContext != null) {
      
      Locale locale = requestContext.getLocale();
      
      // checking if the value corresponds to a null or empty one
      boolean isEmpty = value == null;
      
      if (!isEmpty) {
        
        for (ITypeFormatter formatter : FORMATTERS) {
          
          if (formatter.supports(value) && formatter.isEmpty(value)) {
            
            isEmpty = true;
            break;
          }
        }
      }
      
      // computing the text for the value
      if (isEmpty) {
        
        // the value is empty
        if (formatEmptyValues) {
          
          text =
              requestContext.getThemeMessage(ControllerUtils.EMPTY_VALUES_CODE);
          
        } else {
          
          text = "";
        }
        
      } else {
        
        // getting the formatter for the value
        ITypeFormatter formatter = null;
        
        for (ITypeFormatter theFormatter : FORMATTERS) {
          
          if (theFormatter.supports(value)) {
            
            formatter = theFormatter;
            break;
          }
        }
        
        // formatting the value
        if (formatter == null) {
          
          text = String.valueOf(value);
          
        } else {
          
          text =
              formatter.format(value, locale, request, requestContext, textOnly);
        }
      }
    }
    
    return text;
  }
}
